/*
* @Author: mengxianwei mxw1@meitu.com
* @Date: 2024-09-06 11:38:36
* @LastEditors: mengxianwei mxw1@meitu.com
* @LastEditTime: 2024-10-10 15:25:10
*
* @Description:
* 美图云修QT 组件规范化 --- 滑动条组件
*
* 根据业务需求定制化实现 QSlider 控件，
*
* 滑轨支持线性渐变颜色
*
* 已滑过区域支持单色和双色模式（以 0 值为分界线，可针对大大于 0 与小于 0 分别设置背景色）
*
*/

#ifndef MCOMMONSLIDER_H
#define MCOMMONSLIDER_H

#include <QPropertyAnimation>
#include <QWidget>

class MCommonSlider : public QWidget
{
   Q_OBJECT
 public:
   enum StateStyle
   {
       STYLE_NORMAL = 0,
       STYLE_HOVER,
       STYLE_DISABLE
   };

   enum TextAlignment
   {
       ALIGN_LEFT = 0x0001,
       ALIGN_RIGHT = 0x0002,
       ALIGN_HCENTER = 0x0004,
       ALIGN_TOP = 0x0020,
       ALIGN_BOTTOM = 0x0040,
       ALIGN_VCENTER = 0x0080,
   };
   /**
    * @description:              创建自定已滑动条对象
    * @param {QWidget} *parent   父窗口指针
    * @return {*}
    */
   explicit MCommonSlider(QWidget *parent = nullptr);

   /**
    * @description:    这是滑动条最大值与最小值，需保证最小值小于最大值，内部未做校验
    * @param {int} min 最小值
    * @param {int} max 最大值
    * @return {*}
    */
   void setRange(int min, int max);

   /**
    * @description: 获取滑动条最大值
    * @return {*}
    */
   [[nodiscard]] int minimum() const;

   /**
    * @description: 获取滑动条最小值
    * @return {*}
    */
   [[nodiscard]] int maximum() const;

   /**
    * @description:      设置滑动条当前值
    * @param {int} value 当前值
    * @return {*}
    */
   void setValue(int value);

   /**
    * @description: 返回滑动条当前值
    * @return {*}
    */
   [[nodiscard]] int value() const;

   /**
    * @description:      设置滑动条双击滑块时默认值
    * @param {int} value 默认值
    * @return {*}
    */
   void setDefaultValue(int value);

   /**
    * @description:            开启/关闭 滑块点击动画
    * @param {bool} isEnable   是否开启 true-开启 false- 关闭
    * @param {borderMaxWidth}  borderMaxWidth 滑块边框最大值
    * @return {*}
    *
    * 该接口需要在完成相关样式设置后调用
    */
   void setEnableHandleAnimation(bool isEnable, int borderMaxWidth);

   void setSingleStep(int step);

   void setEventEnable(bool isEnable);

   void setHoverState(bool isHover);

   bool isChangeValueIng();

   /**
    * @description:          设置滑动条文字内容
    * @param {QString&} text 文字内容
    * @param {int} flag      文字在滑动条内的对其方式
    * @return {*}
    */
   void setText(const QString &text, int flag);

   /**
    * @description:              设置文字样式
    * @param {QFont&} font       文字 font
    * @param {QColor} &color     文字颜色
    * @param {StateStyle} state  滑动条状态
    * @return {*}
    */
   void setTextStyle(const QFont &font, const QColor &color, StateStyle state);

   /**
    * @description:              设置滑动条背景色
    * @param {QColor} &color     背景色
    * @param {StateStyle} state  滑动条状态
    * @return {*}
    */
   void setBgStyle(const QColor &color, StateStyle state);

   /**
    * @description:                      设置滑动条滑轨样式
    * @param {int} height                滑轨高度
    * @param {int} radius                滑轨圆角
    * @param {QList<QColor>} &colorList  滑轨背景色，支持线性渐变
    * @param {StateStyle} state          滑动条状态
    * @return {*}
    */
   void setGrooveBgStyle(int height, int radius, const QList<QColor> &colorList, StateStyle state);

   /**
    * @description:                      设置滑动条已滑动区域颜色，支持单色和双色模式（见文件注释）
    * @param {QList<QColor>} &colorList  背景色，支持线性渐变
    * @param {StateStyle} state          滑动条状态
    * @return {*}
    */
   void setSubPageBgStyle(const QList<QColor> &colorList, StateStyle state);

   /**
    * @description:                设置滑块样式
    * @param {int} width           滑块宽度
    * @param {int} height          滑块高度
    * @param {int} radius          滑块圆角
    * @param {QColor} &color       滑块背景色
    * @param {StateStyle} state    滑动条状态
    * @return {*}
    */
   void setHandleBgStyle(int width, int height, int radius, const QColor &color, StateStyle state);

   /**
    * @description:              设置滑块边框样式
    * @param {int} width         边框宽度
    * @param {QColor} &color     边框颜色
    * @param {StateStyle} state  滑动条状态
    * @return {*}
    */
   void setHandleBorderStyle(int width, const QColor &color, StateStyle state);

 signals:
   /**
    * @description:        通知当前正在拖动滑块的值
    * @param {int} value   滑动条当前值
    * @return {*}
    */
   void valueChanging(int value);

   /**
    * @description:        滑动条的最终值
    * @param {int} value   滑动条当前值
    * @return {*}
    */
   void valueChanged(int value);

   /**
    * @description:        通知当前按下滑块
    * @param {int} value   滑动条当前值
    * @return {*}
    */
   void sliderHandlePress(int value);

   /**
    * @description:        通知当前正在松开滑块
    * @param {int} value   滑动条当前值
    * @return {*}
    */
   void sliderHandleRelease(int value);

 protected:
   void paintEvent(QPaintEvent *event) override;
   void resizeEvent(QResizeEvent *event) override;
   void showEvent(QShowEvent *event) override;
   void mousePressEvent(QMouseEvent *event) override;
   void mouseReleaseEvent(QMouseEvent *event) override;
   void mouseMoveEvent(QMouseEvent *event) override;
   void mouseDoubleClickEvent(QMouseEvent *event) override;
   void enterEvent(QEvent *event) override;
   void leaveEvent(QEvent *event) override;
   void keyPressEvent(QKeyEvent *ev) override;
   void wheelEvent(QWheelEvent *e) override;
   void keyReleaseEvent(QKeyEvent *event) override;

 private:
   // 绘制滑动条背景
   void drawSliderBg(QPainter *painter);
   // 绘制滑动条滑轨
   void drawSliderGroove(QPainter *painter);
   // 绘制已划过区域颜色
   void drawSliderSubPage(QPainter *painter);
   // 绘制滑块
   void drawSliderHandle(QPainter *painter);
   // 绘制文字
   void drawSliderText(QPainter *painter);

 private:
   // 重新计算矩形大小
   inline void recalculateRectangle();
   // 计算滑块位置
   inline QPointF calculateSliderHandlePos();
   // 计算当前值
   inline int calculateCurValue(int mousePosX);
   // 设置默认样式
   void setDefaultStyle();

   void createAnimation();

   static inline void startAnimation(QPropertyAnimation *animation);

   static inline void stopAnimation(QPropertyAnimation *animation);

 private:
   QFont textFont_;
   QColor textColor_;
   QFont textHoverFont_;
   QColor textHoverColor_;
   QFont textDisableFont_;
   QColor textDisableColor_;

   // 滑动条 三态 背景颜色
   QColor sliderBgColor_;
   QColor sliderBgHoverColor_;
   QColor sliderBgDisableColor_;

   // 滑动条 滑轨 正常背景颜色、 高度、圆角
   QList<QColor> sliderGrooveBgColorList_;
   int sliderGrooveHeight_;
   int sliderGrooveRadius_;

   // 滑动条 滑轨 高亮背景颜色、 高度、圆角
   QList<QColor> sliderGrooveHoverBgColorList_;
   int sliderGrooveHoverHeight_;
   int sliderGrooveHoverRadius_;

   // 滑动条 滑轨 禁用背景颜色、 高度、圆角
   QList<QColor> sliderGrooveDisableBgColorList_;
   int sliderGrooveDisableHeight_;
   int sliderGrooveDisableRadius_;

   QList<QColor> sliderZeroScaleColorList_;

   // 滑动条 三态 背景颜色
   QList<QColor> sliderSubPageBgColorList_;
   QList<QColor> sliderSubPageHoverBgColorList_;
   QList<QColor> sliderSubPageDisableBgColorList_;

   QColor sliderHandleBgColor_;
   int sliderHandleWidth_;
   int sliderHandleHeight_;
   int sliderHandleRadius_;

   QColor sliderHandleHoverBgColor_;
   int sliderHandleHoverWidth_;
   int sliderHandleHoverHeight_;
   int sliderHandleHoverRadius_;

   QColor sliderHandleDisableBgColor_;
   int sliderHandleDisableWidth_;
   int sliderHandleDisableHeight_;
   int sliderHandleDisableRadius_;

   QColor sliderHandleBorderColor_;
   int sliderHandleBorderWidth_;

   QColor sliderHandleHoverBorderColor_;
   int sliderHandleHoverBorderWidth_;

   QColor sliderHandleDisableBorderColor_;
   int sliderHandleDisableBorderWidth_;

   int maxValue_{100};
   int minValue_{0};
   int curValue_{0};
   int lastValue_{0};
   int defaultValue_{0};
   int textAlignmentFlag_{0};
   int singleStep_{1};
   int borderMaxWidth_{0};
   double sliderIncrement{0.0};
   double curHandleBorderWidth_{2.0};
   std::atomic<bool> isDragable{false};
   std::atomic<bool> isHovered{false};
   std::atomic<bool> handleAnimationEnable_{false};
   std::atomic<bool> eventEnable_{true};
   bool mouseFirstPressedOnHandle_{false};
   QString sliderTextContent_;
   QRectF sliderBgRect;
   QRectF sliderGrooveRect;
   QRectF sliderHandleRect;
   QRectF sliderMouseRect;

   QPropertyAnimation *zoomInAnimation_{};
   QPropertyAnimation *zoomOutAnimation_{};
};

#endif // MCOMMONSLIDER_H
